#include"Lock_Guard.hpp"
#include"Thread.hpp"
#include<iostream>
#include <iostream>
#include <vector>
#include<mutex>

using namespace ThreadModule;
//静态锁
//pthread_mutex_t getmutex = PTHREAD_MUTEX_INITIALIZER;//静态锁
class ThreadData
{
    public:
        ThreadData(const std::string& threadname,int& ticked,std::mutex& mutex)
        :_threadname(threadname),_tickeds(ticked),_total(0),_mutex(mutex)
        {}
        ~ThreadData()
        {}
    public:
        std::string _threadname;
        int& _tickeds;
        int _total;
        // pthread_mutex_t& _mutex;
        std::mutex& _mutex;
};
int g_tickets = 10000; // 共享资源，没有保护的, 临界资源
void route(ThreadData* ptr)
{
    while(true)
    {
        //加锁:本质是将并行执行--》串行执行，加锁的粒度越细越好
        //线程竞争锁是自由竞争的，竞争锁的能力太强，就会导致其他线程抢不到锁，---造成其他线程的饥饿问题！！！
        //pthread_mutex_lock(&ptr->_mutex);     动态锁
        //pthread_mutex_lock(&getmutex);        静态锁
        //LockGuard mutex(&ptr->_mutex);        自己封装的RAII锁
        // std::lock_guard<std::mutex> lock(ptr->_mutex);  //C++11RAII锁
        ptr->_mutex.lock();                     //C++11锁
        //模拟一次抢票逻辑              
        if(ptr->_tickeds > 0)         
        {
            usleep(1000);
            printf("%s is runing ,get ticked: %d\n",
            ptr->_threadname.c_str(),ptr->_tickeds);
            ptr->_tickeds--;
            //pthread_mutex_unlock(&ptr->_mutex);//解锁
            //pthread_mutex_unlock(&getmutex);
            ptr->_mutex.unlock();
            ptr->_total++;
        }
        else
        {
            //pthread_mutex_unlock(&ptr->_mutex);//解锁
            //pthread_mutex_unlock(&getmutex);
            ptr->_mutex.unlock();
            break;
        }
    }
    return ;
}
const int num = 4;
int main()
{
    //动态锁
    // pthread_mutex_t mutex;
    // pthread_mutex_init(&mutex,nullptr);
    //C++11锁
    std::mutex mutex;
    //创建一批线程
    std::vector<Thread<ThreadData*>> threads;
    std::vector<ThreadData*> datas;
    for(int i = 0;i < num;i++)
    {
        std::string name = "thread-" + std::to_string(i+1);
        ThreadData* _ptr = new ThreadData(name,g_tickets,mutex);
        threads.emplace_back(route,_ptr,name);
        datas.emplace_back(_ptr);
    }
    //启动一批线程
    for(auto& thread:threads)
    {
        thread.Start();
    }
    //等待一批线程
    for(auto& thread:threads)
    {
        thread.Join();
        std::cout<<"wait thread name: "<<thread.name()<<std::endl;
    }
    for(auto data: datas)
    {
      std::cout<<"name: "<<data->_threadname<<"total is: "<<data->_total<<std::endl; 
      delete data; 
      //pthread_mutex_destroy(&data->_mutex);
      data->_mutex.~mutex();
    }
    return 0;
}